// ColorPalette.cpp : implementation file
//

#include "stdafx.h"
#include "ansieditor.h"
#include "ColorPalette.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CColorPalette

CColorPalette::CColorPalette()
{
	m_nHoverColor = -1;
	m_bDowned = FALSE;
	m_nForeColor = 16;
	m_nBackColor = 0;
	m_bVert = FALSE;
}

CColorPalette::~CColorPalette()
{
}


BEGIN_MESSAGE_MAP(CColorPalette, CStatic)
	//{{AFX_MSG_MAP(CColorPalette)
	ON_WM_LBUTTONUP()
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_RBUTTONDBLCLK()
	ON_WM_SYSCOLORCHANGE()
	ON_WM_SYSKEYDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CColorPalette message handlers

void CColorPalette::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	CColorBox *pcb = (CColorBox*)GetParent();
	if(pcb->m_bVert)
	{
		dc.BitBlt(0, 0, 39, 200, &m_memdc, 0, 0, SRCCOPY);
		if(m_nHoverColor != -1)
		{
			CPen pen1(PS_SOLID, 1, GetSysColor(COLOR_HIGHLIGHT));
			CPen pen2(PS_SOLID, 2, m_bDowned? m_clrDowned: m_clrSelected);

			dc.SelectObject(&pen2);
			dc.SelectObject(GetStockObject(NULL_BRUSH));
			
			CRect rect(2 + (m_nHoverColor / 9) * 18, 36 + (m_nHoverColor % 9) * 18, 0, 0);
			rect.right = rect.left + 15;
			rect.bottom = rect.top + 15;
			dc.Rectangle(rect);
			rect.InflateRect(2, 2, 1, 1);
			dc.SelectObject(&pen1);
			dc.Rectangle(rect);
			dc.SelectObject(GetStockObject(BLACK_PEN));
		}
	}
	else
	{
		dc.BitBlt(0, 0, 200, 39, &m_memdc, 0, 0, SRCCOPY);
		if(m_nHoverColor != -1)
		{
			CPen pen1(PS_SOLID, 1, GetSysColor(COLOR_HIGHLIGHT));
			CPen pen2(PS_SOLID, 2, m_bDowned? m_clrDowned: m_clrSelected);

			dc.SelectObject(&pen2);
			dc.SelectObject(GetStockObject(NULL_BRUSH));
			
			CRect rect(36 + (m_nHoverColor % 9) * 18, 2 + (m_nHoverColor / 9) * 18, 0, 0);
			rect.right = rect.left + 15;
			rect.bottom = rect.top + 15;
			dc.Rectangle(rect);
			rect.InflateRect(2, 2, 1, 1);
			dc.SelectObject(&pen1);
			dc.Rectangle(rect);
			dc.SelectObject(GetStockObject(BLACK_PEN));
		}
	}


//	CRect rect;
//	GetClientRect(rect);
//	dc.Rectangle(rect);
}

void CColorPalette::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	
	CStatic::PreSubclassWindow();
	UpdateColors();
	DrawMemDC();
}

void CColorPalette::OnMouseMove(UINT nFlags, CPoint point) 
{
	CColorBox *pcb = (CColorBox*)GetParent();

	CRect rect;
	GetClientRect(rect);
	CString sText;
	if(rect.PtInRect(point))
	{
		if(GetCapture() != this)
		{
			sText.LoadString(IDS_PALETTE);
			AfxExtractSubString(sText, sText, 0);
			gpFrame->m_wndStatusBar.SetPaneText(0, sText, TRUE);
			SetCapture();
		}
		// Show Hover Color
		int nHoverColor = -1;
		CPoint pt(point);

		if(pcb->m_bVert)
		{
			pt.x -= 0;
			pt.y -= 35;
			int x, y;
			x = pt.x / 18;
			y = pt.y / 18;
			
			if(pt.x > -2 && x >=0 && x <= 1 && y >=0 && y <= 8)
			{
				nHoverColor = y + x * 9;
			}
		}
		else
		{
			pt.x -= 35;
			pt.y -= 0;
			int x, y;
			x = pt.x / 18;
			y = pt.y / 18;
			
//			afxDump << x << "," << y << "@\n";
			if(pt.x > -2 && x >=0 && x <= 8 && y >=0 && y <= 1)
			{
				nHoverColor = x + y * 9;
			}
		}

		if(nHoverColor != m_nHoverColor)
		{
			m_nHoverColor = nHoverColor;
			Invalidate();
		}
	}
	else
	{
		sText.LoadString(AFX_IDS_IDLEMESSAGE);
		gpFrame->m_wndStatusBar.SetPaneText(0, sText, TRUE);
		if(!m_bDowned)
		{
			ReleaseCapture();
		}
		m_nHoverColor = -1;
		Invalidate();
	}
	CStatic::OnMouseMove(nFlags, point);
}

void CColorPalette::OnLButtonDown(UINT nFlags, CPoint point) 
{
	m_bDowned = TRUE;
	Invalidate();	
	CStatic::OnLButtonDown(nFlags, point);
}

void CColorPalette::OnLButtonUp(UINT nFlags, CPoint point) 
{
//	ReleaseCapture();
	//CColorBox *pcb = (CColorBox*)GetParent();

	m_bDowned = FALSE;
	if(m_nHoverColor != -1)// && m_nForeColor != m_nHoverColor)
	{
		m_nForeColor = m_nHoverColor;
		if((m_nForeColor + 1) % 9 == 0)
		{
			GetAppContext()->m_pView->m_bForeTransparent = TRUE;
		}
		else
		{
			GetAppContext()->m_pView->m_bForeTransparent = FALSE;
			GetAppContext()->m_pView->OnForeColor(GetForeColor(), GetKeyState(VK_CONTROL) < 0);
		}
		UpdateSampleColor();
	}
	Invalidate();
	CStatic::OnLButtonUp(nFlags, point);
}

void CColorPalette::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	OnLButtonDown(nFlags, point);	
}

void CColorPalette::OnRButtonDown(UINT nFlags, CPoint point) 
{
//	m_nHoverColor = m_nHoverColor % 8;
	m_bDowned = TRUE;
	Invalidate();
	CStatic::OnRButtonDown(nFlags, point);
}

void CColorPalette::OnRButtonUp(UINT nFlags, CPoint point) 
{
	m_bDowned = FALSE;
	if(m_nHoverColor != -1 && m_nBackColor != m_nHoverColor)
	{
		m_nBackColor = m_nHoverColor % 9;
		if(m_nBackColor == 8)
		{
			GetAppContext()->m_pView->m_bBackTransparent = TRUE;
		}
		else
		{
			GetAppContext()->m_pView->m_bBackTransparent = FALSE;
			GetAppContext()->m_pView->OnBackColor(m_nBackColor, GetKeyState(VK_CONTROL) < 0);
		}
		UpdateSampleColor();
	}
	Invalidate();
	CStatic::OnRButtonUp(nFlags, point);
}

void CColorPalette::OnRButtonDblClk(UINT nFlags, CPoint point) 
{
	OnRButtonDown(nFlags, point);
}

void CColorPalette::UpdateSampleColor()
{
	m_memdc.SelectObject(GetStockObject(BLACK_PEN));
	m_memdc.SelectObject(GetStockObject(NULL_BRUSH));
	CRect rect;
	rect.SetRect(13, 14, 25, 26);
	if(GetAppContext()->m_pView->m_bBackTransparent)
	{
		DrawMonitor(m_memdc, rect, RGB(255, 255, 255), GetSysColor(COLOR_BTNFACE), RGB(255, 0, 255));
	}
	else
	{
		m_memdc.FillSolidRect(rect, ANSI_COLOR_TO_RGB[m_nBackColor]);
	}
	m_memdc.Rectangle(rect);
	rect.SetRect(6, 7, 18, 19);
	if(GetAppContext()->m_pView->m_bForeTransparent)
	{
		DrawMonitor(m_memdc, rect, RGB(0, 0, 0),RGB(255, 255, 255), RGB(0, 128, 128));
	}
	else
	{
		m_memdc.FillSolidRect(rect, ANSI_COLOR_TO_RGB[GetForeColor()]);
	}
	m_memdc.Rectangle(rect);

	CColorBox *pcb = (CColorBox*)GetParent();
 	pcb->UpdateSampleText(FALSE);
}

void CColorPalette::DrawMemDC()
{
	CColorBox *pcb = (CColorBox*)GetParent();
	// Initialize m_memdc
	CClientDC dc(this);
	m_memdc.DeleteDC();
	m_memdc.CreateCompatibleDC(&dc);
	m_membmp.DeleteObject();

	if(pcb->m_bVert)
	{
		m_membmp.CreateCompatibleBitmap(&dc, 36, 201);
		m_memdc.SelectObject(&m_membmp);
		m_memdc.FillSolidRect(0, 0, 50, 300, GetSysColor(COLOR_BTNFACE));
	}
	else
	{
		m_membmp.CreateCompatibleBitmap(&dc, 200, 36);
		m_memdc.SelectObject(&m_membmp);
		m_memdc.FillSolidRect(0, 0, 300, 50, GetSysColor(COLOR_BTNFACE));
	}

	m_memdc.SelectObject(GetStockObject(BLACK_PEN));
	m_memdc.SelectObject(GetStockObject(NULL_BRUSH));

	if(pcb->m_bVert)
	{
		CRect rect(2, 1, 33, 31);
		m_memdc.DrawEdge(rect, BDR_RAISEDOUTER|BDR_SUNKENINNER, BF_LEFT|BF_TOP|BF_RIGHT|BF_BOTTOM|BF_MONO);

		UpdateSampleColor();
		
		int y = 0, x;
		for(x = 0; x < 2; x++)
		{
			for(y = 0; y < 8; y++)
			{
				rect.left = 3 + x * 18;
				rect.top = 37 + y * 18;
				rect.right = rect.left + 12;
				rect.bottom = rect.top + 12;
				m_memdc.FillSolidRect(rect, ANSI_COLOR_TO_RGB[y + x * 8]);
				m_memdc.Rectangle(rect);
			}
		}
		x = 0;
		rect.left = 3 + x * 18;
		rect.top = 37 + y * 18;
		rect.right = rect.left + 12;
		rect.bottom = rect.top + 12;
		DrawMonitor(m_memdc, rect, RGB(255, 255, 255), GetSysColor(COLOR_BTNFACE), RGB(255, 0, 255));
		rect.left += 18;
		rect.right += 18;
		DrawMonitor(m_memdc, rect, RGB(0, 0, 0),RGB(255, 255, 255), RGB(0, 128, 128));
	}
	else
	{
		CRect rect(1, 2, 31, 33);
		m_memdc.DrawEdge(rect, BDR_RAISEDOUTER|BDR_SUNKENINNER, BF_LEFT|BF_TOP|BF_RIGHT|BF_BOTTOM|BF_MONO);

		UpdateSampleColor();

		int x = 0, y;
		for(y = 0; y < 2; y++)
		{
			for(x = 0; x < 8; x++)
			{
				rect.left = 37 + x * 18;
				rect.top = 3 + y * 18;
				rect.right = rect.left + 12;
				rect.bottom = rect.top + 12;
				m_memdc.FillSolidRect(rect, ANSI_COLOR_TO_RGB[x + y * 8]);
				m_memdc.Rectangle(rect);
			}
		}
		y = 0;
		rect.left = 37 + x * 18;
		rect.top = 3 + y * 18;
		rect.right = rect.left + 12;
		rect.bottom = rect.top + 12;
		DrawMonitor(m_memdc, rect, RGB(255, 255, 255), GetSysColor(COLOR_BTNFACE), RGB(255, 0, 255));
		rect.top += 18;
		rect.bottom += 18;
		DrawMonitor(m_memdc, rect, RGB(0, 0, 0),RGB(255, 255, 255), RGB(0, 128, 128));
	}
}

void CColorPalette::OnSysColorChange() 
{
	CStatic::OnSysColorChange();

	UpdateColors();
	DrawMemDC();
	Invalidate(FALSE);
	UpdateWindow();
}

COLORREF LightenColor(COLORREF col,double factor)
{
	if(factor > 0.0 && factor <= 1.0)
	{
		BYTE red,green,blue,lightred,lightgreen,lightblue;
		red = GetRValue(col);
		green = GetGValue(col);
		blue = GetBValue(col);
		lightred = (BYTE)((factor * (255 - red)) + red);
		lightgreen = (BYTE)((factor * (255 - green)) + green);
		lightblue = (BYTE)((factor * (255 - blue)) + blue);
		col = RGB(lightred, lightgreen, lightblue);
	}
	return(col);
}

void CColorPalette::UpdateColors()
{
	COLORREF clr = GetSysColor(COLOR_HIGHLIGHT);
	m_clrSelected = LightenColor(clr,0.7);
	m_clrDowned = LightenColor(clr,0.5);
}

void CColorPalette::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if(GetCapture() == this)
	{
		ReleaseCapture();
		m_nHoverColor = -1;
		Invalidate();
		UpdateWindow();
	}
}

void CColorPalette::DrawMonitor(CDC &dc, const CRect &rect, COLORREF clr1, COLORREF clr2, COLORREF clr3)
{
	CPen pen(PS_SOLID, 1, clr2);
	CPen *pOldPen = dc.SelectObject(&pen);
	CRect rc(rect);
	dc.FillSolidRect(rc, clr1);
	rc.DeflateRect(3, 3, 3, 3);
	dc.FillSolidRect(rc, clr3);
	rc.InflateRect(2, 2, 2, 2);
	dc.Rectangle(rc);
	dc.SelectObject(pOldPen);
	COLORREF clrBtnFace = GetSysColor(COLOR_BTNFACE);
	dc.SetPixelV(rect.left, rect.top, clrBtnFace);
	dc.SetPixelV(rect.right - 1, rect.top, clrBtnFace);
	dc.SetPixelV(rect.left, rect.bottom - 1, clrBtnFace);
	dc.SetPixelV(rect.right - 1, rect.bottom - 1, clrBtnFace);
}
